#!/bin/bash

TIMESTAMP=`date +"%F_%T"`
DIR="analysis_$TIMESTAMP"

TMPDIR="/tmp/ILAA"
BASIC_BLOCKS=$TMPDIR/"basicblocks_$$"
PATTERN=$TMPDIR/"pattern_$$"
CURRBLOCK=$TMPDIR/"currblock_$$"
TMPOUT=$TMPDIR/"temp_$$"
LOOP_REGIONS=$TMPDIR/"loops_$$"
ADDRESSES=$TMPDIR/"addresses_$$"
CURRADDRESS=$TMPDIR/
ALIASED=$TMPDIR/"aliased_$$"
RAW_ALIASED=$TMPDIR/"rawaliased_$$"
DERIVED=$TMPDIR/"parent_$$"

MYSQLPREFIXN="mysql -uroot -ppassword -D ILAA -B -N -e "
MYSQLPREFIX="mysql -uroot -ppassword -D ILAA -B -e "
TABLE=ILAA

#example records in analysis.in
#   1   :2 : 3  :   4  :   5    :   6          : 7           : 8   : 9     : 10     : 11            : 12   : 13
#hello.c:21:load:al=106:var=ptr2:addr=163323752:valName=tmp22:bb=bb:inst=13:fun=main:state=0x9bb6f50:size=4:type=i32**
#hello.c:21:geptr:al=109:var=tmp23:addr=163323260:elePtr=tmp24,eaddr=163323264:bb=bb:inst=13:fun=main:state=0x9bb6f50:size=4:type=i32*

# 1:  source code
# 2:  line in source code
# 3:  store|load|geptr (getelementptr)
# 4:  line in llvm assembly code
# 5:  name of variable
# 6:  address of variable
# 7:  value name in instruction (load/store); or element pointer (geptr)
# 8:  basic block
# 9:  basic block instance identifier (unique each time the same basic block is encountered)
# 10: function name
# 11: klee state
# 12: size of variable
# 13: type of variable

# What it means
# store: var (i32*) = valName (i32);
# load: valName (i32) = var (i32*);
# getelementptr: elePtr (i32 **) = var (i32**) + offset;


mkdir $TMPDIR 2>/dev/null

# Identify looped basic blocks to analyze
# these are blocks with multiple iterations

if [ "$1" == "" ]; then
   echo Usage: $0 file_filter
   exit 0
fi

mkdir $DIR 2>/dev/null

REGEX=$1
echo Applying the following filter\:
echo $REGEX
echo
echo


echo iterations   srcfile   srcline   bb   fun   run
$MYSQLPREFIXN "SELECT MAX(iter) AS iterations,srcfile,srcline, bb,fun, run FROM (SELECT COUNT(*) AS iter,srcfile,srcline,bb,fun, run from (SELECT DISTINCT srcfile,srcline,bb,inst,fun, run FROM $TABLE WHERE LENGTH(srcfile)>0 AND srcfile REGEXP '$REGEX' GROUP BY bb,inst,fun, run)subquery GROUP BY srcline,bb,fun,run)subquery2 WHERE iter>1 GROUP BY bb,fun,run" | sort -n -r | sort -k 5 > $BASIC_BLOCKS
cat $BASIC_BLOCKS
echo

#BASIC_BLOCKS=basic_block4.txt

#skipped=0
while read line; do
#  if [ $skipped -eq 0 ]; then
#     skipped=1
#     continue
#  fi

  array=(`echo $line`)

  echo Analyzing basic block\:
  echo $line
  srcfile=${array[1]}
  bb=${array[3]}
  fun=${array[4]}
  run=${array[5]}
  
  filename=$(echo $srcfile | tr " " "_" | tr "/" "_" )

#  echo $srcfile, $bb, $fun

#  $MYSQLPREFIXN "SELECT DISTINCT addr FROM $TABLE WHERE bb='$bb' AND fun='$fun';" > $ADDRESSES

echo $line > $DIR/"$run$filename$fun$bb.detail"
$MYSQLPREFIX "SELECT t3.stores>1 AS WW, (t3.stores>0 AND t1.loads>0) AS WR, t1.loads>1 AS RR, t1.loads, t3.stores ,t1.aliased_vars, GROUP_CONCAT(t2.var,':',t2.type) AS parent_vars,t1.addr from (SELECT COUNT(DISTINCT inst) AS loads,GROUP_CONCAT(DISTINCT var, ':', type)as aliased_vars, addr FROM $TABLE 
WHERE bb='$bb' AND fun='$fun' AND run=$run AND instr='load' GROUP BY addr)t1 
LEFT JOIN (SELECT COUNT(DISTINCT inst) AS stores,addr FROM $TABLE WHERE bb='$bb' AND fun='$fun'  AND run=$run AND instr='store' GROUP BY addr)t3 ON t1.addr = t3.addr
LEFT JOIN (SELECT distinct var,valname,type FROM $TABLE WHERE  valname REGEXP 'tmp[0-9]' AND (instr='geptr' OR type like '%**') AND fun='$fun' AND run=$run)t2 ON LOCATE(CONCAT(t2.valname,':',t2.type), t1.aliased_vars)>0 
GROUP BY t1.addr ORDER BY aliased_vars;" > $DIR/"$run$filename$fun$bb.detail"

echo $run$filename$fun >> $DIR/filefunlist

echo $line > $DIR/"$run$filename$fun$bb.result"
$MYSQLPREFIXN "SELECT DISTINCT IF(t3.stores>1,'WW','') AS ww, IF(t3.stores>0 AND t1.loads>0,'WR','') AS wr, IF(t1.loads>1,'RR','') AS rr, IFNULL(t1.aliased_vars,'') AS aliased_vars, IFNULL(GROUP_CONCAT(t2.var,':',t2.type),'') AS parent_vars from (SELECT COUNT(DISTINCT inst) AS loads,GROUP_CONCAT(DISTINCT var, ':', type)as aliased_vars, addr FROM $TABLE 
WHERE bb='$bb' AND fun='$fun'  AND run=$run AND instr='load' GROUP BY addr)t1 
LEFT JOIN (SELECT COUNT(DISTINCT inst) AS stores,addr FROM $TABLE WHERE bb='$bb' AND fun='$fun'  AND run=$run AND instr='store' GROUP BY addr)t3 ON t1.addr = t3.addr
LEFT JOIN (SELECT distinct var,valname,type FROM $TABLE WHERE  valname REGEXP 'tmp[0-9]' AND (instr='geptr' OR type like '%**') AND fun='$fun' AND run=$run)t2 ON LOCATE(CONCAT(t2.valname,':',t2.type), t1.aliased_vars)>0 
GROUP BY t1.addr  ORDER BY aliased_vars;" | tee $DIR/"$run$filename$fun$bb.result"

done < $BASIC_BLOCKS

exit 0

